module cic_filter
(
    input                       clk         , 
    input                       rstn        , 
    input       [3:0]           dat_in      , 
    output  reg signed [26:0]   dat_out     , 
    output  reg                 clk_vld_out            
);
//没有参数化
//----------------------------------------------------
reg     [26:0]  section_out1    ; 
reg     [26:0]  section_out2    ; 
reg     [26:0]  section_out3    ; 
reg     [26:0]  section_out4    ; 
reg     [26:0]  section_out5    ; 

reg     [26:0]  section_out5_r  ;  
reg     [26:0]  section_out5_2r ; 

reg     [26:0]  section_out6_r  ; 
reg     [26:0]  section_out7_r  ; 
reg     [26:0]  section_out8_r  ; 
reg     [26:0]  section_out9_r  ; 

wire    [26:0]  section_out6    ; 
wire    [26:0]  section_out7    ; 
wire    [26:0]  section_out8    ; 
wire    [26:0]  section_out9    ; 
wire    [26:0]  section_out10   ; 

reg     [4:0]   cur_cnt; //24倍降采样
wire            phase_1; //时钟有效信号，每24时钟周期出现一个phase_1脉冲

//------------------ Integrator ------------------
always @(posedge clk or negedge rstn)
begin
    if (!rstn)
    begin
        section_out1 <= 27'd0;
        section_out2 <= 27'd0;
        section_out3 <= 27'd0;
        section_out4 <= 27'd0;
        section_out5 <= 27'd0;
    end
    else
    begin
        section_out1 <= dat_in       + section_out1;
        section_out2 <= section_out1 + section_out2;
        section_out3 <= section_out2 + section_out3;
        section_out4 <= section_out3 + section_out4;
        section_out5 <= section_out4 + section_out5;
    end
end

//---------- clock divider ------------------
always @(posedge clk or negedge rstn)
begin
    if (!rstn)
        cur_cnt <= 5'd0;
    else if (cur_cnt == 5'd23) // 5'b10111
        cur_cnt <= 5'd0; // 重置计数器
    else 
        cur_cnt <= cur_cnt + 5'd1;
end

assign  phase_1 = (cur_cnt == 5'd0);  //和matlab对应，1修改为0

//------------------ Comb ------------------
// 无符号数的差分操作需要防溢出
assign section_out6  = (section_out5_r >= section_out5_2r) ? 
                       (section_out5_r - section_out5_2r) : 27'd0;
assign section_out7  = (section_out6 >= section_out6_r) ? 
                       (section_out6 - section_out6_r) : 27'd0;
assign section_out8  = (section_out7 >= section_out7_r) ? 
                       (section_out7 - section_out7_r) : 27'd0;
assign section_out9  = (section_out8 >= section_out8_r) ? 
                       (section_out8 - section_out8_r) : 27'd0;
assign section_out10 = (section_out9 >= section_out9_r) ? 
                       (section_out9 - section_out9_r) : 27'd0;

always @(posedge clk or negedge rstn)
begin
    if (!rstn)
    begin
        section_out5_r  <= 27'd0;
        section_out5_2r <= 27'd0;
        section_out6_r  <= 27'd0;
        section_out7_r  <= 27'd0;
        section_out8_r  <= 27'd0;
        section_out9_r  <= 27'd0;
    end
    else if (phase_1)
    begin
        section_out5_r  <= section_out5;
        section_out5_2r <= section_out5_r; //延迟一拍信号
        section_out6_r  <= section_out6;  
        section_out7_r  <= section_out7;
        section_out8_r  <= section_out8;
        section_out9_r  <= section_out9;
    end
end 

//模块的输出如果是组合逻辑产生的，通常需要加一级寄存器打拍，以优化时序
//------------------ Output Register (无符号转有符号) ------------------
always @(posedge clk or negedge rstn)
begin
    if (!rstn)
        dat_out <= 27'sd0;
    else if (phase_1)
        dat_out <= section_out10 - 27'd67108864; // 减去 2^26
        //dat_out <= {~section_out10[26], section_out10[25:0]};
end

always @(posedge clk or negedge rstn)
begin
    if (!rstn)
        clk_vld_out <= 1'b0;
    else
        clk_vld_out <= phase_1;
end 

endmodule